home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / util / recvstats.sh < prev    next >
Linux/UNIX/POSIX Shell Script  |  1994-08-01  |  7KB  |  284 lines

  1. #! /bin/sh
  2. #    $Header: /usr/people/sam/fax/util/RCS/recvstats.sh,v 1.5 1994/02/28 14:24:43 sam Rel $
  3. #
  4. # FlexFAX Facsimile Software
  5. #
  6. # Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  7. # Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  8. # Permission to use, copy, modify, distribute, and sell this software and 
  9. # its documentation for any purpose is hereby granted without fee, provided
  10. # that (i) the above copyright notices and this permission notice appear in
  11. # all copies of the software and related documentation, and (ii) the names of
  12. # Sam Leffler and Silicon Graphics may not be used in any advertising or
  13. # publicity relating to the software without the specific, prior written
  14. # permission of Sam Leffler and Silicon Graphics.
  15. # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16. # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17. # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18. # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19. # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20. # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22. # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23. # OF THIS SOFTWARE.
  24. #
  25.  
  26. #
  27. # Print Statistics about Received Facsimile.
  28. #
  29. SPOOL=/usr/spool/fax
  30. AWK=nawk
  31.  
  32. PATH=/bin:/usr/bin:/etc
  33. test -d /usr/ucb  && PATH=$PATH:/usr/ucb        # Sun and others
  34. test -d /usr/bsd  && PATH=$PATH:/usr/bsd        # Silicon Graphics
  35. test -d /usr/5bin && PATH=/usr/5bin:$PATH:/usr/etc    # Sun and others
  36. test -d /usr/sbin && PATH=/usr/sbin:$PATH        # 4.4BSD-derived
  37.  
  38. # look for an an awk: nawk, gawk, awk
  39. ($AWK '{}' </dev/null >/dev/null) 2>/dev/null ||
  40.     { AWK=gawk; ($AWK '{}' </dev/null >/dev/null) 2>/dev/null || AWK=awk; }
  41.  
  42. FILES=
  43. SORTKEY=-sender
  44.  
  45. while [ x"$1" != x"" ] ; do
  46.     case $1 in
  47.     -send*|-csi|-dest*|-speed|-rate|-format)
  48.         SORTKEY=$1;;
  49.     -*)        echo "Usage: $0 [-sortkey] [files]"; exit 1;;
  50.     *)        FILES="$FILES $1";;
  51.     esac
  52.     shift
  53. done
  54. if [ -z "$FILES" ]; then
  55.     FILES=$SPOOL/etc/xferlog
  56. fi
  57.  
  58. #
  59. # Construct awk rules to collect information according
  60. # to the desired sort key.  There are two rules for
  61. # each; to deal with the two different formats that
  62. # have existed over time.
  63. #
  64. case $SORTKEY in
  65. -send*|-csi)
  66.     AWKRULES='$2 == "RECV" && NF == 9  { acct($3, $7, $8, $5, $6, $9); }
  67.                $2 == "RECV" && NF == 11 { acct($6, $9, $10, $7, $8, $11); }'
  68.     ;;
  69. -dest*)
  70.     AWKRULES='$2 == "RECV" && NF == 9  { acct($4, $7, $8, $5, $6, $9); }
  71.               $2 == "RECV" && NF == 11 { acct($5, $9, $10, $7, $8, $11); }'
  72.     ;;
  73. -speed|-rate)
  74.     AWKRULES='$2 == "RECV" && NF == 9  { acct($5, $7, $8, $5, $6, $9); }
  75.               $2 == "RECV" && NF == 11 { acct($7, $9, $10, $7, $8, $11); }'
  76.     ;;
  77. -format)
  78.     AWKRULES='$2 == "RECV" && NF == 9  { acct($6, $7, $8, $5, $6, $9); }
  79.               $2 == "RECV" && NF == 11 { acct($8, $9, $10, $7, $8, $11); }'
  80.     ;;
  81. esac
  82.  
  83. #
  84. # Generate an awk program to process the statistics file.
  85. #
  86. tmpAwk=/tmp/xfer$$
  87. trap "rm -f $tmpAwk; exit 1" 0 1 2 15
  88.  
  89. (cat<<'EOF'
  90. #
  91. # Convert hh:mm:ss to seconds.
  92. #
  93. func cvtTime(s)
  94. {
  95.     t = i = 0;
  96.     for (n = split(s, a, ":"); i++ < n; )
  97.     t = t*60 + a[i];
  98.     return t;
  99. }
  100.  
  101. func setupDigits()
  102. {
  103.   digits[0] = "0"; digits[1] = "1"; digits[2] = "2";
  104.   digits[3] = "3"; digits[4] = "4"; digits[5] = "5";
  105.   digits[6] = "6"; digits[7] = "7"; digits[8] = "8";
  106.   digits[9] = "9";
  107. }
  108.  
  109. #
  110. # Format seconds as hh:mm:ss.
  111. #
  112. func fmtTime(t)
  113. {
  114.     v = int(t/3600);
  115.     result = "";
  116.     if (v > 0) {
  117.     if (v >= 10)
  118.         result = digits[int(v/10)];
  119.     result = result digits[int(v%10)] ":";
  120.     t -= v*3600;
  121.     }
  122.     v = int(t/60);
  123.     if (v >= 10 || result != "")
  124.     result = result digits[int(v/10)];
  125.     result = result digits[int(v%10)];
  126.     t -= v*60;
  127.     return (result ":" digits[int(t/10)] digits[int(t%10)]);
  128. }
  129.  
  130. #
  131. # Setup a map for histogram calculations.
  132. #
  133. func setupMap(s, map)
  134. {
  135.     n = split(s, a, ":");
  136.     for (i = 1; i <= n; i++)
  137.     map[a[i]] = i;
  138. }
  139.  
  140. #
  141. # Add pages to a histogram.
  142. #
  143. func addToMap(key, ix, pages, map)
  144. {
  145.     if (key == "") {
  146.     for (i in map)
  147.         key = key ":";
  148.     }
  149.     n = split(key, a, ":");
  150.     a[map[ix]] += pages;
  151.     t = a[1];
  152.     for (i = 2; i <= n; i++)
  153.       t = t ":" a[i];
  154.     return t;
  155. }
  156.  
  157. #
  158. # Return the name of the item with the
  159. # largest number of accumulated pages.
  160. #
  161. func bestInMap(totals, map)
  162. {
  163.    n = split(totals, a, ":");
  164.    imax = 1; max = -1;
  165.    for (j = 1; j <= n; j++)
  166.        if (a[j] > max) {
  167.        max = a[j];
  168.        imax = j;
  169.        }
  170.    split(map, a, ":");
  171.    return a[imax];
  172. }
  173.  
  174. #
  175. # Sort array a[l..r]
  176. #
  177. function qsort(a, l, r) {
  178.     i = l;
  179.     k = r+1;
  180.     item = a[l];
  181.     for (;;) {
  182.     while (i < r) {
  183.             i++;
  184.         if (a[i] >= item)
  185.         break;
  186.         }
  187.     while (k > l) {
  188.             k--;
  189.         if (a[k] <= item)
  190.         break;
  191.         }
  192.         if (i >= k)
  193.         break;
  194.     t = a[i]; a[i] = a[k]; a[k] = t;
  195.     }
  196.     t = a[l]; a[l] = a[k]; a[k] = t;
  197.     if (k != 0 && l < k-1)
  198.     qsort(a, l, k-1);
  199.     if (k+1 < r)
  200.     qsort(a, k+1, r);
  201. }
  202.  
  203. #
  204. # Accumulate a statistics record.
  205. #
  206. func acct(key, pages, time, br, df, status)
  207. {
  208.     gsub("\"", "", key);
  209.     gsub("^ +", "", key);
  210.     gsub(" +$", "", key);
  211.     recvpages[key] += pages;
  212.     if (pages == 0 && time > 60)
  213.     time = 0;
  214.     recvtime[key] += cvtTime(time);
  215.     gsub("\"", "", status);
  216.     if (status != "")
  217.     recverrs[key]++;
  218.     gsub("\"", "", br);
  219.     recvrate[key] = addToMap(recvrate[key], br, pages, rateMap);
  220.     gsub("\"", "", df);
  221.     recvdata[key] = addToMap(recvdata[key], df, pages, dataMap);
  222. }
  223.  
  224. #
  225. # Print a rule between the stats and the totals line.
  226. #
  227. func printRule(n, s)
  228. {
  229.     r = "";
  230.     while (n-- >= 0)
  231.     r = r s;
  232.     printf "%s\n", r;
  233. }
  234.  
  235. BEGIN        { FS="\t";
  236.           rates = "2400:4800:7200:9600:12000:14400";
  237.           setupMap(rates, rateMap);
  238.           datas = "1-D MR:2-D MR:2-D Uncompressed Mode:2-D MMR";
  239.           setupMap(datas, dataMap);
  240.         }
  241. END        { OFS="\t"; setupDigits();
  242.           maxlen = 15;
  243.           nsorted = 0;
  244.           for (i in recvpages) {
  245.               l = length(i);
  246.               if (l > maxlen)
  247.             maxlen = l;
  248.               sorted[nsorted++] = i;
  249.           }
  250.           qsort(sorted, 0, nsorted-1);
  251.           fmt = "%-" maxlen "." maxlen "s";    # e.g. %-24.24s
  252.           printf fmt " %5s %8s %6s %4s %7s %7s\n",
  253.               "Sender", "Pages", "Time", "Pg/min",
  254.               "Errs", "TypRate", "TypData";
  255.           tpages = 0;
  256.           ttime = 0;
  257.           terrs = 0;
  258.           for (k = 0; k < nsorted; k++) {
  259.               i = sorted[k];
  260.               t = recvtime[i]/60; if (t == 0) t = 1;
  261.               n = recvpages[i]; if (n == 0) n = 1;
  262.               brate = best
  263.               printf fmt " %5d %8s %6.1f %4d %7d %7s\n",
  264.               i, recvpages[i], fmtTime(recvtime[i]),
  265.               recvpages[i] / t, recverrs[i],
  266.               bestInMap(recvrate[i], rates),
  267.               bestInMap(recvdata[i], datas);
  268.             tpages += recvpages[i];
  269.             ttime += recvtime[i];
  270.             terrs += recverrs[i];
  271.           }
  272.           printRule(maxlen+1+5+1+8+6+1+4+1+7+1+7, "-");
  273.           t = ttime/60; if (t == 0) t = 1;
  274.           printf fmt " %5d %8s %6.1f %4d\n",
  275.               "Total", tpages, fmtTime(ttime), tpages/t, terrs;
  276.         }
  277. EOF
  278. echo "$AWKRULES"
  279. )>$tmpAwk
  280. $AWK -f $tmpAwk $FILES
  281.